/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-10-16     86188       the first version
 */
#include "rtthread.h"
#include "rtdevice.h"
#include <uart_dma.h>

/*===============================================================================================*/
#ifdef BSP_USING_USBDEVICE
#define VCOM_NAME  "vcom"

static rt_size_t vcom_send(char *data, rt_size_t size);
static rt_size_t vcom_recv(char *buffer, rt_int32_t timeout);
static rt_err_t  vcom_input(rt_device_t dev, rt_size_t size);
static rt_err_t  vcom_output(rt_device_t dev, void* buf);
static int       vcom_init(uint32_t baud_rate);

USER_Uart USER_VCOM = {RT_NULL, RT_NULL, RT_NULL, vcom_send, vcom_recv, vcom_input, vcom_output, vcom_init};

static rt_size_t vcom_send(char *data, rt_size_t size)
{
    rt_device_write(USER_VCOM.serial, 0, data, size);
    /* 等待数据发送完成 */
    if (rt_mb_recv(USER_VCOM.txmb, RT_NULL, RT_WAITING_FOREVER) != RT_EOK)
    {
        return 0;
    }
    return 0;
}

static rt_size_t vcom_recv(char *buffer, rt_int32_t timeout)
{
    rt_size_t len;
    if (rt_mb_recv(USER_VCOM.rxmb, &len, timeout) != RT_EOK)
    {
        return 0;
    }
    len = rt_device_read(USER_VCOM.serial, 0, buffer, len);
    return len;
}

/* 接收数据回调函数 */
static rt_err_t vcom_input(rt_device_t dev, rt_size_t size)
{
    return rt_mb_send(USER_VCOM.rxmb, size);
}
/* 发送回调函数 */
static rt_err_t vcom_output(rt_device_t dev, void* buf)
{
    return rt_mb_send(USER_VCOM.txmb, (rt_size_t)buf);
}

static int vcom_init(uint32_t baud_rate)
{
    USER_VCOM.serial = rt_device_find(VCOM_NAME);

    if (!USER_VCOM.serial)
    {
        rt_kprintf("find %s failed!\n", VCOM_NAME);
        return RT_ERROR;
    }

    if (USER_VCOM.rxmb == RT_NULL)
    {
        USER_VCOM.rxmb = rt_mb_create("vcom_rxmb", 1, RT_IPC_FLAG_FIFO);
        if (USER_VCOM.rxmb == RT_NULL)
        {
            return RT_ERROR;
        }
    }
    if (USER_VCOM.txmb == RT_NULL)
    {
        USER_VCOM.txmb = rt_mb_create("vcom_txmb", 1, RT_IPC_FLAG_FIFO);
        if (USER_VCOM.txmb == RT_NULL)
        {
            return RT_ERROR;
        }
    }

    rt_device_set_rx_indicate(USER_VCOM.serial, USER_VCOM.input);
    /* 注册发送完成回调函数 */
    rt_device_set_tx_complete(USER_VCOM.serial, USER_VCOM.output);

    /* 接收不能用DMA */
    rt_device_open(USER_VCOM.serial, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX);
    return RT_EOK;
}
#endif
/*===============================================================================================*/


/*===============================================================================================*/
//#ifdef BSP_USING_UART1
//#define UART1_NAME  "uart1"      /* 串口设备名称 */
//
//static rt_size_t uart1_send(char *data, rt_size_t size);
//static rt_size_t uart1_recv(char *buffer, rt_int32_t timeout);
//static rt_err_t  uart1_input(rt_device_t dev, rt_size_t size);
//static rt_err_t  uart1_output(rt_device_t dev, void* buf);
//static int       uart1_init(uint32_t baud_rate);
//
//USER_Uart USER_UART1 = {RT_NULL, RT_NULL, RT_NULL, uart1_send, uart1_recv, uart1_input, uart1_output, uart1_init};
//
//static rt_size_t uart1_send(char *data, rt_size_t size)
//{
//    rt_device_write(USER_UART1.serial, 0, data, size);
//    if (rt_mb_recv(USER_UART1.txmb, RT_NULL, RT_WAITING_FOREVER) != RT_EOK)
//    {
//        return 0;
//    }
//    return 0;
//}
//
//static rt_size_t uart1_recv(char *buffer, rt_int32_t timeout)
//{
//    rt_size_t len;
//    if (rt_mb_recv(USER_UART1.rxmb, &len, timeout) != RT_EOK)
//    {
//        return 0;
//    }
//    len = rt_device_read(USER_UART1.serial, 0, buffer, len);
//    return len;
//}
//
///* 数据回调函数 */
//static rt_err_t uart1_input(rt_device_t dev, rt_size_t size)
//{
//    return rt_mb_send(USER_UART1.rxmb, size);
//}
//static rt_err_t uart1_output(rt_device_t dev, void* buf)
//{
//    return rt_mb_send(USER_UART1.txmb, (rt_size_t)buf);
//}
//
//static int uart1_init(uint32_t baud_rate)
//{
//    /* 获取设备，创建邮箱 */
//    USER_UART1.serial = rt_device_find(UART1_NAME);
//    if (USER_UART1.serial == RT_NULL)
//    {
//        rt_kprintf("find %s failed!\n", UART1_NAME);
//    }
//    USER_UART1.rxmb = rt_mb_create("uart1_rxmb", 1, RT_IPC_FLAG_FIFO);
//    if (USER_UART1.rxmb == RT_NULL)
//    {
//        rt_kprintf("failed to create uart1rxmb!\n");
//    }
//    USER_UART1.txmb = rt_mb_create("uart1_txmb", 1, RT_IPC_FLAG_FIFO);
//    if (USER_UART1.txmb == RT_NULL)
//    {
//        rt_kprintf("failed to create uart1txmb!\n");
//    }
//
//    /* step2：修改串口配置参数 */
//    struct serial_configure config  = RT_SERIAL_CONFIG_DEFAULT; //初始化配置参数
//    config.baud_rate = baud_rate;                               //修改波特率
//    config.bufsz = 512;
//    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
//    rt_device_control(USER_UART1.serial, RT_DEVICE_CTRL_CONFIG, &config);
//    /* 注册回调 */
//    rt_device_set_rx_indicate(USER_UART1.serial, USER_UART1.input);
//    rt_device_set_tx_complete(USER_UART1.serial, USER_UART1.output);
//
//#ifdef BSP_UART1_RX_USING_DMA
//    rt_device_open(USER_UART1.serial, RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX);    //以DMA读取方式打开串口设备
//#else
//    rt_device_open(USER_UART1.serial, RT_DEVICE_FLAG_INT_RX);    //以中断读取方式打开串口设备
//#endif
//    return RT_EOK;
//}
//#endif
/*===============================================================================================*/



/*===============================================================================================*/
#ifdef BSP_USING_UART3
#define UART3_NAME  "uart3"      /* 串口设备名称 */

static rt_size_t uart3_send(char *data, rt_size_t size);
static rt_size_t uart3_recv(char *buffer, rt_int32_t timeout);
static rt_err_t  uart3_input(rt_device_t dev, rt_size_t size);
static int       uart3_init(uint32_t baud_rate);

USER_Uart USER_UART3 = {RT_NULL, RT_NULL, RT_NULL, uart3_send, uart3_recv, uart3_input, RT_NULL, uart3_init};

static rt_size_t uart3_send(char *data, rt_size_t size)
{
    return rt_device_write(USER_UART3.serial, 0, data, size);
}

static rt_size_t uart3_recv(char *buffer, rt_int32_t timeout)
{
    rt_ubase_t len;
    if (rt_mb_recv(USER_UART3.rxmb, &len, timeout) != RT_EOK)
    {
        return 0;
    }
    len = rt_device_read(USER_UART3.serial, 0, buffer, len);
    return len;
}

/* 接收数据回调函数 */
static rt_err_t uart3_input(rt_device_t dev, rt_size_t size)
{
    /* 发送邮件 */
    return rt_mb_send(USER_UART3.rxmb, size);
}

static int uart3_init(uint32_t baud_rate)
{
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
    USER_UART3.serial = rt_device_find(UART3_NAME);

    if (!USER_UART3.serial)
    {
        rt_kprintf("find %s failed!\n", UART3_NAME);
        return RT_ERROR;
    }
    if (USER_UART3.rxmb == RT_NULL)
    {
        USER_UART3.rxmb = rt_mb_create("uart3_rxmb", 1, RT_IPC_FLAG_FIFO);
        if (USER_UART3.rxmb == RT_NULL)
        {
            return RT_ERROR;
        }
    }

    /* step2：修改串口配置参数 */
    config.baud_rate = baud_rate;   //修改波特率
    config.bufsz = 512;

    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
    rt_device_control(USER_UART3.serial, RT_DEVICE_CTRL_CONFIG, &config);
    rt_device_set_rx_indicate(USER_UART3.serial, USER_UART3.input);

#ifdef BSP_UART3_RX_USING_DMA
    rt_device_open(USER_UART3.serial, RT_DEVICE_FLAG_DMA_RX);    //以DMA读取方式打开串口设备
#else
    rt_device_open(USER_UART3.serial, RT_DEVICE_FLAG_INT_RX);    //以中断读取方式打开串口设备
#endif
    return RT_EOK;
}
#endif
/*===============================================================================================*/



/*===============================================================================================*/
#ifdef BSP_USING_UART4
#define UART4_NAME  "uart4"      /* 串口设备名称v */

static rt_size_t uart4_send(char *data, rt_size_t size);
static rt_size_t uart4_recv(char *buffer, rt_int32_t timeout);
static rt_err_t  uart4_input(rt_device_t dev, rt_size_t size);
static int       uart4_init(uint32_t baud_rate);

USER_Uart USER_UART4 = {RT_NULL, RT_NULL, RT_NULL, uart4_send, uart4_recv, uart4_input, RT_NULL, uart4_init};

static rt_size_t uart4_send(char *data, rt_size_t size)
{
    return rt_device_write(USER_UART4.serial, 0, data, size);
}

static rt_size_t uart4_recv(char *buffer, rt_int32_t timeout)
{
    rt_ubase_t len;
    if (rt_mb_recv(USER_UART4.rxmb, &len, timeout) != RT_EOK)
    {
        return 0;
    }
    len = rt_device_read(USER_UART4.serial, 0, buffer, len);
    return len;
}

/* 接收数据回调函数 */
static rt_err_t uart4_input(rt_device_t dev, rt_size_t size)
{
    /* 发送邮件 */
    return rt_mb_send(USER_UART4.rxmb, size);
}

static int uart4_init(uint32_t baud_rate)
{
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
    USER_UART4.serial = rt_device_find(UART4_NAME);

    if (!USER_UART4.serial)
    {
        rt_kprintf("find %s failed!\n", UART4_NAME);
        return RT_ERROR;
    }
    if (USER_UART4.rxmb == RT_NULL)
    {
        USER_UART4.rxmb = rt_mb_create("uart4_rxmb", 1, RT_IPC_FLAG_FIFO);
        if (USER_UART4.rxmb == RT_NULL)
        {
            return RT_ERROR;
        }
    }

    /* step2：修改串口配置参数 */
    config.baud_rate = baud_rate;   //修改波特率
    config.bufsz = 512;

    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
    rt_device_control(USER_UART4.serial, RT_DEVICE_CTRL_CONFIG, &config);
    rt_device_set_rx_indicate(USER_UART4.serial, USER_UART4.input);
#ifdef BSP_UART4_RX_USING_DMA
    rt_device_open(USER_UART4.serial, RT_DEVICE_FLAG_DMA_RX);    //以DMA读取方式打开串口设备
#else
    rt_device_open(USER_UART4.serial, RT_DEVICE_FLAG_INT_RX);    //以中断读取方式打开串口设备
#endif
    return RT_EOK;
}
#endif
/*===============================================================================================*/




/*===============================================================================================*/
#ifdef BSP_USING_UART6
#define UART6_NAME  "uart6"      /* 串口设备名称v */

static rt_size_t uart6_send(char *data, rt_size_t size);
static rt_size_t uart6_recv(char *buffer, rt_int32_t timeout);
static rt_err_t  uart6_input(rt_device_t dev, rt_size_t size);
static int       uart6_init(uint32_t baud_rate);

USER_Uart USER_UART6 = {RT_NULL, RT_NULL, RT_NULL, uart6_send, uart6_recv, uart6_input, RT_NULL, uart6_init};

static rt_size_t uart6_send(char *data, rt_size_t size)
{
    return rt_device_write(USER_UART6.serial, 0, data, size);
}

static rt_size_t uart6_recv(char *buffer, rt_int32_t timeout)
{
    rt_size_t len;
    if (rt_mb_recv(USER_UART6.rxmb, &len, timeout) != RT_EOK)
    {
        return 0;
    }
    len = rt_device_read(USER_UART6.serial, 0, buffer, len);
    return len;
}

/* 接收数据回调函数 */
static rt_err_t uart6_input(rt_device_t dev, rt_size_t size)
{
    /* 发送邮件 */
    return rt_mb_send(USER_UART6.rxmb, size);
}

static int uart6_init(uint32_t baud_rate)
{
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
    USER_UART6.serial = rt_device_find(UART6_NAME);

    if (!USER_UART6.serial)
    {
        rt_kprintf("find %s failed!\n", UART6_NAME);
        return RT_ERROR;
    }
    if (USER_UART6.rxmb == RT_NULL)
    {
        USER_UART6.rxmb = rt_mb_create("uart6_rxmb", 1, RT_IPC_FLAG_FIFO);
        if (USER_UART6.rxmb == RT_NULL)
        {
            return RT_ERROR;
        }
    }

    /* step2：修改串口配置参数 */
    config.baud_rate = baud_rate;   //修改波特率
    config.stop_bits = STOP_BITS_2;
    config.data_bits = DATA_BITS_9;
    config.parity    = PARITY_EVEN;
    config.bufsz = 128;

    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
    rt_device_control(USER_UART6.serial, RT_DEVICE_CTRL_CONFIG, &config);
    rt_device_set_rx_indicate(USER_UART6.serial, USER_UART6.input);
#ifdef BSP_UART6_RX_USING_DMA
    rt_device_open(USER_UART6.serial, RT_DEVICE_FLAG_DMA_RX);    //以DMA读取方式打开串口设备
#else
    rt_device_open(USER_UART6.serial, RT_DEVICE_FLAG_INT_RX);    //以中断读取方式打开串口设备
#endif
    return RT_EOK;
}
#endif
/*===============================================================================================*/

static int uart_init(void)
{

#ifdef BSP_USING_USBDEVICE
    if (USER_VCOM.init(0) == RT_EOK)
    {
        rt_kprintf("vcom init successful!\r\n");
    }
#endif

//#ifdef BSP_USING_UART1
//    if (USER_UART1.init(500000) == RT_EOK)
//    {
//        rt_kprintf("uart1 dma init successful!\r\n");
//    }
//#endif

#ifdef BSP_USING_UART3
    if (USER_UART3.init(115200) == RT_EOK)
    {
        rt_kprintf("uart3 dma init successful!\r\n");
    }
#endif

#ifdef BSP_USING_UART4
    if (USER_UART4.init(115200) == RT_EOK)
    {
        rt_kprintf("uart4 dma init successful!\r\n");
    }
#endif

#ifdef BSP_USING_UART5
    if (USER_UART5.init(500000) == RT_EOK)
    {
        rt_kprintf("uart5 dma init successful!\r\n");
    }
#endif

#ifdef BSP_USING_UART6
    if (USER_UART6.init(100000) == RT_EOK)
    {
        rt_kprintf("uart6 dma init successful!\r\n");
    }
#endif

    return RT_EOK;
}

INIT_ENV_EXPORT(uart_init); /* 使用组件自动初始化机制 */
